package com.jack.concurrency;

import java.util.concurrent.locks.StampedLock;

/**
 * Created by zhang_j on 2019/12/10
 * beginx:0.0,y:0.0
 * endx:1.0,y:1.0
 * begincurrentX:1.0,currentY:1.0
 * endcurrentX:1.0,currentY:1.0
 * 1.4142135623730951
 * begincurrentX:1.0,currentY:1.0
 * endcurrentX:1.0,currentY:1.0
 * 1.4142135623730951
 * begincurrentX:1.0,currentY:1.0
 * endcurrentX:1.0,currentY:1.0
 * 1.4142135623730951
 * beginx:1.0,y:1.0
 * endx:3.0,y:3.0
 */
public class MyStamppedLock {
    public static void main(String[] args) {
        final Point point= new Point();
        new Thread(()->point.move(1,1)).start();
        new Thread(()-> System.out.println(point.distanceFromOrigin())).start();
        new Thread(()->point.move(2,2)).start();
        new Thread(()-> System.out.println(point.distanceFromOrigin())).start();
        new Thread(()-> System.out.println(point.distanceFromOrigin())).start();
    }
}
class Point {
    private double x, y;
    private final StampedLock sl = new StampedLock();

    void move(double deltaX, double deltaY) { // an exclusively locked method
        System.out.println("begin"+"x:"+x+",y:"+y);
        long stamp = sl.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            sl.unlockWrite(stamp);
            System.out.println("end"+"x:"+x+",y:"+y);
        }
    }

    double distanceFromOrigin() { // A read-only method
        long stamp = sl.tryOptimisticRead();
        double currentX = x, currentY = y;
        System.out.println("begin"+"currentX:"+currentX+",currentY:"+currentY);
        if (!sl.validate(stamp)) {
            stamp = sl.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);
            }
        }
        System.out.println("end"+"currentX:"+currentX+",currentY:"+currentY);
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}